package service

import (
	"errors"

	"go-gin-init/app/DB/mysql"

	"go-gin-init/app/models/model"
	"go-gin-init/common/xerr"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

var post_service PostService

type PostService interface {
	CreatPost(postMap map[string]interface{}) error
	UpdatePost(post *model.Post) error
	FindByTitle(title string) (*model.Post, error)
	FindById(id int64) (*model.Post, error)
	DeletePost(id int64) error
	FindListPage(SearchTest string, PageNum int64, PageSize int64) ([]*model.Post, error)
}

type defaultPostModel struct {
	*gorm.DB
}

func NewDefaultPostModel() PostService {
	once.Do(func() {
		post_service = &defaultPostModel{mysql.GetGormDB()}
	})
	return post_service
}

func (m *defaultPostModel) FindListPage(SearchTest string, PageNum int64, PageSize int64) ([]*model.Post, error) {

	var posts []model.Post
	offset := (PageNum - 1) * PageSize
	result := m.Where("title LIKE ? and isDelete = 0", "%"+SearchTest+"%").Offset(int(offset)).Limit(int(PageSize)).Find(&posts)
	if result.Error != nil {
		zap.L().Error("sql-POST: FindListPage err", zap.Error(result.Error))
		return nil, result.Error
	}
	var _model []*model.Post
	for i := 0; i < len(posts); i++ {
		_model = append(_model, &posts[i])
	}
	return _model, nil

}

func (m *defaultPostModel) FindById(id int64) (*model.Post, error) {

	var post = model.Post{}
	tx := m.Where("id = ? and isDelete = 0", id).First(&post)
	err := tx.Error
	switch err {
	case nil:
		return &post, nil
	case gorm.ErrRecordNotFound:
		zap.L().Warn("sql-POST: FindListPage err", zap.Error(xerr.NewErrCode(xerr.RECORD_NOT_EXIT)))
		return nil, ErrNotFound
	default:
		zap.L().Error("sql-POST: FindById err", zap.Error(err))
		return nil, err
	}
}

func (m *defaultPostModel) FindByTitle(title string) (*model.Post, error) {

	var post = model.Post{}
	tx := m.Where("title = ? and isDelete = 0", title).First(&post)
	err := tx.Error
	switch err {
	case nil:
		return &post, nil
	case gorm.ErrRecordNotFound:
		zap.L().Warn("sql POST FindByTitle Warn", zap.Error(xerr.NewErrCode(xerr.RECORD_NOT_EXIT)))
		return nil, ErrNotFound
	default:
		zap.L().Error("sql-POST: FindByTitle err", zap.Error(err))
		return nil, err
	}
}

func (m *defaultPostModel) CreatPost(postMap map[string]interface{}) error {
	tx := m.Model(&model.Post{}).Create(postMap)
	err := tx.Error
	if err != nil {
		return err
	}

	if tx.RowsAffected == 0 {
		zap.L().Warn("sql-POST: CreatPost err:影响行数为空")
		return errors.New("影响行数为空")
	}

	return nil
}

func (m *defaultPostModel) UpdatePost(post *model.Post) error {
	tx := m.Model(post).Where("id = ? and isDelete = 0", post.Id).Updates(model.Post{Title: post.Title, Content: post.Content, Tags: post.Tags})
	err := tx.Error
	if err != nil {
		zap.L().Error("sql-POST: UpdatePost err", zap.Error(err))
		return err
	}

	if tx.RowsAffected == 0 {
		zap.L().Warn("sql-POST: UpdatePost err:修改行数为空")
		return errors.New("修改行数为空")
	}

	return nil
}

// Delete 软删除
func (m *defaultPostModel) DeletePost(id int64) error {

	tx := m.Model(&model.Post{}).Where("id = ? and isDelete = 0", id).Update("isDelete", 1)
	err := tx.Error

	if err != nil {
		zap.L().Error("sql-POST: DeletePost err", zap.Error(err))
		return err
	}
	if tx.RowsAffected == 0 {
		zap.L().Warn("sql-POST: UpdatePost err:修改行数为空")
		return errors.New("修改行数为空")
	}
	return nil
}
